import string
from nltk.translate import bleu_score
from nltk.tokenize import TweetTokenizer


def calc_bleu_many(cand_seq, ref_sequences):
    '''
    计算多个序列的bleu评分 todo 这里ref_sequences去除了回答序列的第一个字符，为什么这么做

    cand_seq: 模型预测的下一话token id序列 list列表
    ref_seq: label 目标回答的token id序列 list列表

    todo 计算分数的公式和原理
    '''
    sf = bleu_score.SmoothingFunction()
    return bleu_score.sentence_bleu(ref_sequences, cand_seq,
                                    smoothing_function=sf.method1,
                                    weights=(0.5, 0.5))

def calc_bleu(cand_seq, ref_seq):
    '''
    计算bleu评分

    cand_seq: 模型预测的下一话token id序列
    ref_seq: label 目标回答的token id序列
    '''
    return calc_bleu_many(cand_seq, [ref_seq])

def tokenize(s):
    '''
    NLTK中用于分割文本为独立的词字
    preserve_case表示是否保存大小写，False表示不保留，全部都是小写
    参考链接：https://blog.csdn.net/qq_25885951/article/details/125869569
    '''
    return TweetTokenizer(preserve_case=False).tokenize(s)

def untokenize(words):
    '''
    string.punctuation表示标点符号
    words：一个句子的单词list【单词1，单词2】
    '''
    # 以下方法的作用是将单词重新组成短语字符串，如果不是标点符号或者'符号，则拼接空格后直接拼接到字符串中，否则则直接拼接
    return "".join([" " + i if not i.startswith("'") and i not in string.punctuation else i for i in words]).strip()
